﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Extensions;
using Abp.Runtime.Session;
using Mt.Site.Application.Authorization.Permissions.Dto;
using Mt.Site.Core.Base.Authorization;
using Mt.Site.Core.Base.Authorization.Level;
using Mt.Site.Core.Navigations;
using Mt.Site.Core.Navigations.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Application.Authorization.Permissions
{
    [AbpAuthorize]
    public class PermissionAppService : MtSiteAppServiceBase, IPermissionAppService
    {
        private readonly IMtUserNavigationManager _mtUserNavigationManager;

        public PermissionAppService(IMtUserNavigationManager mtUserNavigationManager)
        {
            _mtUserNavigationManager = mtUserNavigationManager;
        }

        // 完整 （供selection筛选）
        public async Task<ListResultDto<FlatPermissionWithLevelDto>> GetAllPermissionsAsync()
        {
            var userId = AbpSession.GetUserId();
            var permissions = new List<Permission>();

            foreach (var p in PermissionManager.GetAllPermissions())
            {
                if (p.GetWeightFromPermission() >= LevelEnum.Super.RawValue())
                {
                    continue;
                }

                if (await UserManager.IsGrantedAsync(userId, p))
                {
                    permissions.Add(p);
                }
            }

            var rootPermissions = permissions.Where(p => p.Parent == null);

            var result = new List<FlatPermissionWithLevelDto>();

            foreach (var rootPermission in rootPermissions)
            {
                var level = 0;
                AddPermission(rootPermission, permissions, result, level);
            }

            return new ListResultDto<FlatPermissionWithLevelDto>
            {
                Items = result
            };
        }

        private void AddPermission(Permission permission, IReadOnlyList<Permission> allPermissions, List<FlatPermissionWithLevelDto> result, int level)
        {
            var flatPermission = ObjectMapper.Map<FlatPermissionWithLevelDto>(permission);
            flatPermission.Level = level;
            result.Add(flatPermission);

            if (permission.Children == null)
            {
                return;
            }

            var children = allPermissions.Where(p => p.Parent != null && p.Parent.Name == permission.Name).ToList();

            foreach (var childPermission in children)
            {
                AddPermission(childPermission, allPermissions, result, level + 1);
            }
        }


        // 完整 （供筛选）
        public async Task<List<FlatMenuPermissionDto>> GetAllMenuPermissionsAsync()
        {
            var result = new List<FlatMenuPermissionDto>();

            if(AbpSession.TenantId == null)
            {
                return result;
            }

            var userId = AbpSession.GetUserId();
            var menus = await _mtUserNavigationManager.GetBackEndContentMenusForBindingAsync();

            for (int i = 0,length = menus.Count; i < length; i++)
            {
                var userMenu = menus[i];
                foreach (MtBackEndUserMenuItem item in userMenu.Items)
                {
                    var level = 0;
                    await AddMenuPermission(item,null, result,level, userId);
                }
            }

            return result;
        }

        private async Task AddMenuPermission(MtBackEndUserMenuItem menuItem, MtBackEndUserMenuItem parent, List<FlatMenuPermissionDto> result, int level, long userId)
        {
            //todo:待细分
            if(!await UserManager.IsMenuItemGrantedAsync(userId, menuItem.Name))
            {
                return;
            }

            var flatPermission = new FlatMenuPermissionDto
            {
                Name = menuItem.Name,
                ParentName = parent?.Name,
                DisplayName = menuItem.DisplayName,
                Order = menuItem.Order,
                IsActive = menuItem.IsEnabled
            };
            flatPermission.Level = level;
            result.Add(flatPermission);

            if (menuItem.Items == null || menuItem.Items.Count == 0)
            {
                return;
            }

            foreach (var childPermission in menuItem.Items)
            {
                await AddMenuPermission(childPermission, menuItem, result, level + 1, userId);
            }
        }

        public async Task<List<FlatPermissionWithLevelDto>> GetAllPermissionsOrderByDisplayNameAsync()
        {
            var permissions = await GetAllPermissionsAsync();
            return permissions.Items.OrderBy(p => p.DisplayName).ToList();
        }

        public async Task<string> GetModuleNameByMenuIdAsync(Guid menuId)
        {
            return await _mtUserNavigationManager.GetModuleNameByMenuId(menuId);
        }

        public List<FlatPermissionDto> GetPermissionsByModuleNameAsync(string moduleName)
        {
            var permissions = PermissionManager.GetCustomMenuPermissions(moduleName);
            return permissions.Select(c=> ObjectMapper.Map<FlatPermissionDto>(c)).ToList();
        }
    }
}